package proxy;

import java.lang.reflect.*;

/**
 * /对生成的二进制文件输出然后反编译后获得
 *
 * 可以看到生成的基本是写模板代码  都是try catch return
 */

public final class ProxySubject extends Proxy
        implements Subject {
    private static Method m1;
    private static Method m0;
    private static Method m3;
    private static Method m2;

    public static void main(String[] args) {

    }
    //类加载时候  初始化各Method,method实例持有所有可能的元数据信息,可以将其等同为js中的一个函数引用，之后就可以类比函数调用，将所有涉及到的参数传递给它即可，当然少不了传递this
    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{
                    Class.forName("java.lang.Object")
            });
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            m3 = Class.forName("proxy.Subject").getMethod("doSomething", new Class[0]);
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
        } catch (NoSuchMethodException nosuchmethodexception) {
            throw new NoSuchMethodError(nosuchmethodexception.getMessage());
        } catch (ClassNotFoundException classnotfoundexception) {
            throw new NoClassDefFoundError(classnotfoundexception.getMessage());
        }
    }

    public ProxySubject(InvocationHandler invocationhandler) {
        super(invocationhandler);
    }

    public final boolean equals(Object obj) {
        try {
            return ((Boolean) super.h.invoke(this, m1, new Object[]{
                    obj
            })).booleanValue();
        } catch (Error _ex) {
        } catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
        return false;
    }

    public final int hashCode() {
        try {
            return ((Integer) super.h.invoke(this, m0, null)).intValue();
        } catch (Error _ex) {
        } catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
        return 0;
    }
    // 执行目标方法 会调用InvocationHandler(这里有我们的切入逻辑)
    // 从这里可以清晰的看到 最终调到我们的切入方法时(即invoke),分别i传入的是生成的代理实例，接口方法函数引用,以及客户端传入的直接args

    public final void doSomething() {
        try {
            super.h.invoke(this, m3, null);
            return;
        } catch (Error _ex) {
        } catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final String toString() {
        try {
            return (String) super.h.invoke(this, m2, null);
        } catch (Error _ex) {
        } catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
        return "";
    }


}